#!/usr/bin/perl
# file fork.pl

print "PID = $$\n";     # $$ 保持当前进程的pid，可读，不能改变。

my $child = fork();
die "cannot fork: $!" unless defined $child;

if ($child > 0){    #parent process
    print "parent process: PID=$$, child=$child\n";
}else{
    my $ppid = getppid();       # 子进程，获取父进程的pid
    print "child process: PID=$$, parent=$ppid\n";
}


# fork函数调用时生成一个当前进程的精确拷贝。
# 子进程的这个拷贝拥有所有变量、文件句柄（包括io缓冲区中的数据）和其他数据结构的所有当前值。
# 这个复制的进程甚至具有调用fork的内存。

# 调用fork之后，父进程和子进程都检查函数的返回值。在父进程中，fork返回子进程的pid。
# 在子进程中，fork返回0。代码如果发现它是父进程就会开始做一件事，如果是子进程就会做另一件事。

# fork调用之后父进程和子进程相互通信，可以通过管道或者共享内存来完成。
# 父进程从fork的结果代码中获取子进程的pid，而子进程通过 getppid 获取父进程的pid。

# 默认情况下这样创建的进程都属于同一个进程组，每个进程组都有同一个ID
# $processid = getpgrp([ $pid ]);

# 进程组的每一个成员都共享其父进程创建时打开的文件句柄。
# 特别的它们共享相同的 STDOUT STDIN STDERR。
# 这些可以被任何子进程修改，然而系统会跟踪哪个子进程打开了文件句柄，直到最后一个子进程关闭其对文件句柄的拷贝才会关闭文件。
